<?php
declare (strict_types=1);

namespace app\admin\service\data\ticket;

use app\admin\logic\market\ticket\Ticket as TicketLogic;
use app\admin\logic\market\ticket\TicketCoupon as TicketCouponLogic;
use app\admin\model\market\ticket\TicketCoupon;
use app\admin\service\data\DataService;
use app\course\model\coupon\admin\CouponUser;
use eduline\admin\page\PageList;
use think\annotation\Inject;
use think\db\exception\DbException;
use think\facade\Request;
use think\model\Collection;
use think\Response;

class TicketStat extends DataService
{

    /**
     * @Inject()
     *
     * @var TicketLogic
     */
    protected $ticketLogic;

    /**
     * @Inject()
     *
     * @var TicketCouponLogic
     */
    protected $ticketCouponLogic;

    /**
     * 数据总览
     *
     * @return Response
     */
    public function survey()
    {
        $datas = [
            // 'receive_count' => 0,
            // 'used_count'    => 0,
            // 'expire_count'  => 0
        ];

        $ticketId = Request::get('ticket_id/d', 0);
        $couponId = Request::get('coupon_id/d', 0);
        if ($couponId > 0) {
            // 针对单个活动券
            $datas['receive_count'] = $this->getSingleCouponData(1, $couponId);
            $datas['used_count']    = $this->getSingleCouponData(2, $couponId);
            $datas['expire_count']  = $this->getSingleCouponData(3, $couponId);
        } else {
            // 针对活动总量统计
            // 总领取次数
            $datas['receive_count'] = CouponUser::alias('cu')
                ->join('market_ticket_coupon m', 'm.id = cu.ticket_id and m.ticket_id = ' . $ticketId)
                ->count('cu.id');
            // 总使用次数
            $datas['used_count'] = CouponUser::alias('cu')
                ->join('market_ticket_coupon m', 'm.id = cu.ticket_id and m.ticket_id = ' . $ticketId)
                ->where('cu.status', '<>', 0)
                ->count('cu.id');
            // 总过期次数
            $datas['expire_count'] = CouponUser::alias('cu')
                ->join('market_ticket_coupon m', 'm.id = cu.ticket_id and m.ticket_id = ' . $ticketId)
                ->where('cu.end_time', '<', request()->time())
                ->count('cu.id');
        }

        return $this->parseToData($datas, 1, '获取成功');
    }

    /**
     * 趋势图
     *
     * @return Response
     */
    public function receiveTrend()
    {
        $ticketId  = Request::get('ticket_id/d', 0);
        $couponId  = Request::get('coupon_id/d', 0);
        $where     = [];
        $daterange = $this->parseSelectDaterange();
        $rows      = $this->parseRowsDate($daterange['rows'], ['receive_count' => 0, 'used_count' => 0, 'receive_used_count' => 0, 'expire_count' => 0]);
        if ($couponId > 0) {
            $where['cu.ticket_id'] = $couponId;
        }
        $timeFormat = '%Y-%m-%d';
        // 统计图表
        if ($daterange['days'] == 1) {
            // 按小时,此处一天内的小时数不会重复,因此可以直接按小时取
            $timeFormat = '%H:00';
        }
        // 按天
        $rows = $this->parseRows(
            $this->getStatData(1, $ticketId, $daterange['timespan'], $where, $timeFormat),
            $rows,
            'receive_count'
        );
        // 使用数量
        $rows = $this->parseRows(
            $this->getStatData(2, $ticketId, $daterange['timespan'], $where, $timeFormat),
            $rows,
            'used_count'
        );
        // 使用并使用数量
        $rows = $this->parseRows(
            $this->getStatData(3, $ticketId, $daterange['timespan'], $where, $timeFormat),
            $rows,
            'receive_used_count'
        );
        // 过期数量
        $rows = $this->parseRows(
            $this->getStatData(4, $ticketId, $daterange['timespan'], $where, $timeFormat),
            $rows,
            'expire_count'
        );

        $data['rows'] = $rows;

        return $this->parseToData($data, 1, '获取成功');
    }

    /**
     * 解析统计图指标数据
     *
     * @param $datas
     * @param $rows
     * @param $field
     * @return array|mixed
     */
    protected function parseRows($datas, $rows = [], $field = '')
    {
        if ($datas instanceof Collection) {
            $lists = [];
            foreach ($datas as $item) {
                $lists[] = [
                    'date'     => $item->date,
                    'tp_count' => $item->tp_count
                ];
            }

            $datas = $lists;
            unset($lists);
        }
        $result = array_column($datas, null, 'date');

        foreach ($rows as $key => $row) {
            $time               = $row['date'];
            $rows[$key][$field] = isset($result[$time]) ? $result[$time]['tp_count'] : 0;
        }

        return $rows;
    }

    /**
     * 表格数据
     *
     * @return Response
     * @throws DbException
     */
    public function tableData()
    {
        $ticketId = Request::get('ticket_id/d', 0);
        $couponId = Request::get('coupon_id/d', 0);
        $count    = Request::param('count/d', 20);

        if ($couponId > 0) {
            $data = CouponUser::alias('cu')->with(['user'])
                ->join('market_ticket_coupon m', 'm.id = cu.ticket_id')
                ->where('cu.ticket_id', $couponId)
                ->field([
                    'cu.*',
                    'm.issue_no'    => 'ticket_issue_no',
                    'm.coupon_type' => 'ticket_coupon_type',
                    'm.maxprice'    => 'ticket_maxprice',
                    'm.price'       => 'ticket_price',
                    'm.discount'    => 'ticket_discount',
                ])
                ->paginate($count);
        } else {
            $data = CouponUser::alias('cu')->with(['user'])
                ->join('market_ticket_coupon m', 'm.id = cu.ticket_id and m.ticket_id = ' . $ticketId)
                ->field([
                    'cu.*',
                    'm.issue_no'    => 'ticket_issue_no',
                    'm.coupon_type' => 'ticket_coupon_type',
                    'm.maxprice'    => 'ticket_maxprice',
                    'm.price'       => 'ticket_price',
                    'm.discount'    => 'ticket_discount',
                ])
                ->paginate($count)
                ->each(function ($item) {
                    $item->end_time = $item->end_time ? date('Y-m-d H:i', $item->end_time) : '-';
                });
        }

        $list        = new PageList();
        $list->datas = $data;

        return $list->send();
    }

    /**
     * 获取统计数据
     *
     * @param int    $dataType
     * @param int    $ticketId
     * @param array  $timespan
     * @param array  $where
     * @param string $timeFormat
     * @return array
     */
    private function getStatData(int $dataType, int $ticketId, array $timespan, array $where = [], string $timeFormat = '%Y-%m-%d')
    {
        $field  = [
            'FROM_UNIXTIME(cu.create_time,"' . $timeFormat . '")' => 'date',
            'count(1)'                                            => 'tp_count'
        ];
        $result = [];
        switch ($dataType) {
            // 领取
            case 1:
                $result = CouponUser::alias('cu')
                    ->join('market_ticket_coupon m', 'm.id = cu.ticket_id and m.ticket_id = ' . $ticketId)
                    ->whereBetween('cu.create_time', $timespan)
                    ->where($where)
                    ->field($field)
                    ->group('date')
                    ->select();
                break;
            // 使用
            case 2:
                $result = CouponUser::alias('cu')
                    ->join('market_ticket_coupon m', 'm.id = cu.ticket_id and m.ticket_id = ' . $ticketId)
                    ->whereBetween('cu.update_time', $timespan)
                    ->where('cu.status', '<>', 0)
                    ->where($where)
                    ->field($field)
                    ->group('date')
                    ->select();
                break;
            // 领取并使用
            case 3:
                $result = CouponUser::alias('cu')
                    ->join('market_ticket_coupon m', 'm.id = cu.ticket_id and m.ticket_id = ' . $ticketId)
                    ->whereBetween('cu.create_time', $timespan)
                    ->where('cu.status', '<>', 0)
                    ->where($where)
                    ->field($field)
                    ->group('date')
                    ->select();
                break;
            // 过期
            case 4:
                $result = CouponUser::alias('cu')
                    ->join('market_ticket_coupon m', 'm.id = cu.ticket_id and m.ticket_id = ' . $ticketId)
                    ->whereBetween('cu.end_time', $timespan)
                    ->where('cu.end_time', '<', request()->time())
                    ->where($where)
                    ->field($field)
                    ->group('date')
                    ->select();
                break;
        }

        return $result;
    }

    /**
     * 获取单个优惠券的统计数据
     *
     * @param int $dataType
     * @param int $couponId
     * @return int
     */
    private function getSingleCouponData(int $dataType, int $couponId)
    {
        $count = 0;

        switch ($dataType) {
            case 1:
                // 总领取次数
                $count = CouponUser::where('ticket_id', $couponId)
                    ->count();
                break;
            case 2:
                // 总使用次数
                $count = CouponUser::where('ticket_id', $couponId)
                    ->where('status', '<>', 0)
                    ->count();
                break;
            case 3:
                // 总过期次数
                $count = CouponUser::where('ticket_id', $couponId)
                    ->where('end_time', '<', request()->time())
                    ->count();
                break;
        }

        return $count;
    }

    /**
     * 对比趋势图数据
     *
     * @return Response
     */
    public function contrastTrend()
    {
        // 数据类型,多种优惠券对比
        $columns  = [];
        $dataType = Request::get('data_type/d', 1);
        // 选择的优惠券列表
        $ticketId  = Request::get('ticket_id/d', 0);
        $couponIds = Request::get('coupon_ids/a', []);

        if (is_array($couponIds)) {
            // 日期
            $daterange = $this->parseSelectDaterange();

            $rows = $this->parseRowsDate($daterange['rows']);

            $timeFormat = '%Y-%m-%d';
            // 统计图表
            if ($daterange['days'] == 1) {
                // 按小时,此处一天内的小时数不会重复,因此可以直接按小时取
                $timeFormat = '%H:00';
            }
            foreach ($couponIds as $couponId) {
                $key = 'coupon_' . $couponId;
                // 获取优惠券编号
                $columns[$key] = TicketCoupon::where('id', $couponId)->value('issue_no');
                $where         = [
                    'cu.ticket_id' => $couponId
                ];

                $rows = $this->parseRows(
                    $this->getStatData($dataType, $ticketId, $daterange['timespan'], $where, $timeFormat),
                    $rows,
                    $key
                );

            }
        }

        return $this->parseToData([
            'rows'    => $rows,
            'columns' => $columns
        ], 1, '获取成功');
    }

    /**
     * 对比表格数据
     *
     * @return Response
     */
    public function contrastTableData()
    {
        // 选择的优惠券列表
        $couponIds = Request::get('coupon_ids/a', []);
        $datas     = [];

        foreach ($couponIds as $couponId) {
            $couponId = intval($couponId);
            $item     = $this->ticketCouponLogic->getInfoById($couponId);
            if (!$item->isEmpty()) {
                $item->receive_count = $this->getSingleCouponData(1, $couponId);
                $item->used_count    = $this->getSingleCouponData(2, $couponId);
                $item->expire_count  = $this->getSingleCouponData(3, $couponId);
                $datas[]             = $item->toArray();
            }
        }

        return $this->parseTodata($datas, 1);
    }
}
